/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package bab;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;

/**
 * Cette classe représente les données d'un problème de sac à dos 0/1
 *
 * @author Florent
 */
public class Data {

	private final int numObject; //le nombre d'objects
	private final int[] profits; //leur valeurs
	private final int[] weights; //leur poids
	private int capacity; //la capacité du sac à ne pas dépasser

	private static int seed = 0;

	/**
	 * Permet de générer une instance du pb
	 * @param numItem nombre d'item
	 * @param range le poids et leur valeur ira de 0 à range
	 * @param correlation correlation entre le poid et les valeurs de 1 à 4
	 * 1 = correlation très faible  4 - correlation très forte
	 * @return peut potentiellement retourné null si quelque chose c'est mal passé
	 */
	public static Data dataGenerator(int numItem, int range, int correlation) {
		seed++;
		return dataGenerator(numItem, range, correlation, seed);
	}

	/**
	 * Permet de générer une instance du pb
	 * @param numItem nombre d'item
	 * @param range le poids et leur valeur ira de 0 à range
	 * @param correlation correlation entre le poid et les valeurs de 1 à 4
	 * 1 = correlation très faible  4 - correlation très forte
	 * @param seed graine de depart
	 * @return peut potentiellement retourné null si quelque chose c'est mal passé
	 */
	public static Data dataGenerator(int numItem, int range, int correlation, int seed) {
		assert correlation >= 1 && correlation <= 4;
		int S = 1000;
		int i = seed;
		Runtime rt = Runtime.getRuntime();
		String command = String.format("./generator %d %d %d %d %d", numItem, range, correlation, i, S);
		Process pr;
		Data data = null;

		try {
			pr = rt.exec(command);
			data = new Data(new File("test.in"));
		} catch(IOException e) {
			e.printStackTrace();
			data = null;
		}

		if (data != null &&  data.getCapacity() > numItem * range) {
			data.setCapacity(numItem * range / 4);
		}

		if(data == null) {
			System.out.println("Data null : " + command);
		}

		return data;
	}

	/**
	 *
	 * @param file pointe sur un fichier générer par le generateur
	 * @throws FileNotFoundException
	 */
	public Data(File file) throws FileNotFoundException {
		Scanner scanner = new Scanner(file);
		numObject = scanner.nextInt();

		profits = new int[numObject];
		weights = new int[numObject];

		for (int i = 0; i < numObject; i++) {
			scanner.nextInt(); //id de l'objet qu'on n'utilise pas
			profits[i] = scanner.nextInt();
			weights[i] = scanner.nextInt();
		}

		capacity = scanner.nextInt();

		scanner.close();
	}

	/**
	 * profits.length == weights.length
	 * @param profits valeur des objet
	 * @param weights poids des objet
	 * @param capacity capacité du sac
	 */
	public Data(int[] profits, int[] weights, int capacity) {
		this.numObject = profits.length;
		this.profits = profits;
		this.weights = weights;
		this.capacity = capacity;
	}

	/**
	 * 
	 * @return le nombre d'objet
	 */
	public int getNumObject() {
		return numObject;
	}

	/**
	 * 
	 * @return la valeur des objects
	 */
	public int[] getProfits() {
		return profits;
	}

	/**
	 * 
	 * @return le poids des objects
	 */
	public int[] getWeights() {
		return weights;
	}

	/**
	 * 
	 * @return la capacité du sac
	 */
	public int getCapacity() {
		return capacity;
	}

	/**
	 * Affiche les infos de ce set de donné
	 */
	public void printData() {
		System.out.println("Poids : " + Arrays.toString(weights));
		System.out.println("Valeurs : " + Arrays.toString(profits));
		System.out.println("Capacité : " + capacity);
	}

	/**
	 * 
	 * @param solution
	 * @return calcule le poids d'une solution de cette instance
	 */
	public int solutionWeight(Iterable<Integer> solution) {
		int solW = 0;

		for (int i : solution) {
			solW += weights[i];
		}

		return solW;
	}


	/**
	 * 
	 * @param solution
	 * @return true ssi la solution est acceptable (ie elle ne dépasse pas le poid du sac à dos)
	 */
	public boolean solutionAcceptable(Iterable<Integer> solution) {
		return solutionWeight(solution) <= capacity;
	}

	/**
	 * 
	 * @param capacity 
	 */
	public void setCapacity(int capacity) {
		this.capacity = capacity;
	}
}
